﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
using CMS6Tools.Common;
using System.Text.RegularExpressions;

namespace CMS6Tools.Performances.DataAnalytics
{
    public class PrtgApiClient
    {
        public PrtgApiClient(string apiUrl = "https://prtg.visioninternet.com/", string userName = "Visionrd", string password = "Vision1013!")
        {
            ApiUrl = apiUrl;
            UserName = userName;
            Password = password;
        }

        public string ApiUrl { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }

        public PrtgGetSensorData GetSensorData()
        {
            var url = string.Format("{0}/api/table.xml?content=sensor&count=1000&username={1}&password={2}&columns=objid,name,status,type,interval,active,group,device,url",
                                    ApiUrl.TrimEnd('/'),
                                    UserName,
                                    Password);
            var parameters = new Dictionary<string, string>();
            parameters["filter_group"] = "WEB SITES STATUS";
            var response = WebUtils.DoGet(url, parameters);
            var getSensorData = default(PrtgGetSensorData);
            using (var stringReader = new StringReader(response))
            {
                var xmlSerializer = new XmlSerializer(typeof(PrtgGetSensorData));
                getSensorData = (PrtgGetSensorData)xmlSerializer.Deserialize(stringReader);
            }
            return getSensorData;
        }

        public IEnumerable<PrtgResponseTimeData> GetLivePrtgResponseTimeDataList(string siteID, int count, string format = "xml", int start = -1)
        {
            if (start == -1)
            {
                var totalCount = GetLivePrtgTotalValues(siteID);
                start = totalCount - count;
            }

            var url = string.Format("{0}/api/table.{1}?content=values&output={1}&id={6}&username={2}&password={3}&start={4}&count={5}&columns=datetime,value_,coverage",
                                         ApiUrl.TrimEnd('/'),
                                         format,
                                         UserName,
                                         Password,
                                         start,
                                         count,
                                         siteID);

            var response = WebUtils.DoGet(url);

            return ConvertLiveToResponseTimeData(siteID, response);
        }

        public int GetLivePrtgTotalValues(string siteID)
        {
            var url = string.Format("{0}/api/table.{1}?content=values&output={1}&id={4}&username={2}&password={3}&start=0&count=1&columns=datetime,value_,coverage",
                                         ApiUrl.TrimEnd('/'),
                                         "xml",
                                         UserName,
                                         Password,
                                         siteID);
            var response = WebUtils.DoGet(url);

            return ConvertLiveTotalCount(siteID, response);
        }

        public IEnumerable<PrtgResponseTimeData> GetPrtgResponseTimeDataList(string siteID, DateTime from, DateTime to, int interval=300, string format="csv")
        {
            var url = string.Format("{0}/api/historicdata.{1}?id={7}&username={2}&password={3}&sdate={4}&edate={5}&avg={6}",
                                         ApiUrl.TrimEnd('/'),
                                         format,
                                         UserName,
                                         Password,
                                         from.ToString("yyyy-MM-dd-hh-mm-ss"),
                                         to.ToString("yyyy-MM-dd-hh-mm-ss"),
                                         interval,
                                         siteID); 

            var response = WebUtils.DoGet(url);

            return ConvertToResponseTimeData(siteID, response);
        }

        IEnumerable<PrtgResponseTimeData> ConvertLiveToResponseTimeData(string siteID, string responseTimeXmlResult)
        {
            var list = new List<PrtgResponseTimeData>();

            try
            {
                var xmlDocument = new XmlDocument();
                xmlDocument.LoadXml(responseTimeXmlResult);
                var itemNodes = xmlDocument.SelectNodes("/values/item");
                foreach (XmlNode xmlNode in itemNodes)
                {
                    var responseTimeData = new PrtgResponseTimeData() { SiteID = siteID };

                    responseTimeData.DateTime = xmlNode.SelectSingleNode("datetime").InnerXml;
                    responseTimeData.DateTimeRaw = float.Parse(xmlNode.SelectSingleNode("datetime_raw").InnerXml);
                    responseTimeData.Coverage = float.Parse(xmlNode.SelectSingleNode("coverage_raw").InnerXml);

                    var valueRawNodes = xmlNode.SelectNodes("value_raw");
                    foreach (XmlNode valueRawNode in valueRawNodes)
                    {
                        var channelAttribtue = valueRawNode.Attributes["channel"];
                        if ("Downtime".Equals(channelAttribtue.Value, StringComparison.InvariantCultureIgnoreCase))
                        {
                            responseTimeData.DownTime = float.Parse(valueRawNode.InnerXml);
                        }
                        else if ("Loading time".Equals(channelAttribtue.Value, StringComparison.InvariantCultureIgnoreCase))
                        {
                            responseTimeData.ResponseTime = float.Parse(valueRawNode.InnerXml);
                        }
                    }

                    list.Add(responseTimeData);
                }
            }
            catch
            {
            }

            return list;
        }

        int ConvertLiveTotalCount(string siteID, string responseTimeXmlResult)
        { 
            try
            {
                var xmlDocument = new XmlDocument();
                xmlDocument.LoadXml(responseTimeXmlResult);
                var itemNodes = xmlDocument.SelectSingleNode("/values");
                return int.Parse(itemNodes.Attributes["totalcount"].Value);
            }
            catch
            {
            }

            return 0;
        }
        public string GetSensorURL(string sensorId)
        {
            var url = string.Format("{0}/controls/objectdata.htm?id={1}&objecttype=sensor,aggregation&username={2}&password={3}",
                                         ApiUrl.TrimEnd('/'),
                                         sensorId,
                                         UserName,
                                         Password);

            var response = WebUtils.DoGet(url);
            var regex = new Regex("readonlyproperty\">(((http[s]?:\\/\\/)|(www\\.))[^<]*)<\\/div>", RegexOptions.IgnoreCase);
            var match = regex.Match(response);
            var result = string.Empty;
            if (match.Success)
            {
                return match.Groups[1].Value;
            }
            if (result.StartsWith("www.", StringComparison.CurrentCultureIgnoreCase))
                result = "http://" + result;
            return result;
        }
        IEnumerable<PrtgResponseTimeData> ConvertToResponseTimeData(string siteID, string responseTimeXmlResult)
        {
            var list = new List<PrtgResponseTimeData>();

            try
            {
                var xmlDocument = new XmlDocument();
                xmlDocument.LoadXml(responseTimeXmlResult);
                var itemNodes = xmlDocument.SelectNodes("/histdata/item");
                foreach (XmlNode xmlNode in itemNodes)
                {
                    var responseTimeData = new PrtgResponseTimeData() { SiteID = siteID };

                    responseTimeData.DateTime = xmlNode.SelectSingleNode("datetime").InnerXml;
                    responseTimeData.DateTimeRaw = float.Parse(xmlNode.SelectSingleNode("datetime_raw").InnerXml);
                    responseTimeData.Coverage = float.Parse(xmlNode.SelectSingleNode("coverage_raw").InnerXml);

                    var valueRawNodes = xmlNode.SelectNodes("value_raw");
                    foreach (XmlNode valueRawNode in valueRawNodes)
                    {
                        var channelAttribtue = valueRawNode.Attributes["channel"];
                        if ("Downtime".Equals(channelAttribtue.Value, StringComparison.InvariantCultureIgnoreCase))
                        {
                            responseTimeData.DownTime = float.Parse(valueRawNode.InnerXml);
                        }
                        else if ("Loading time".Equals(channelAttribtue.Value, StringComparison.InvariantCultureIgnoreCase))
                        {
                            responseTimeData.ResponseTime = float.Parse(valueRawNode.InnerXml);
                        }
                    }

                    list.Add(responseTimeData);
                }
            }
            catch
            { 
            }

            return list;
        }

    }
}
